﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;

namespace SharpShare.Configuration {
    [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
    public sealed class CollectableElementAttribute : Attribute {
        public CollectableElementAttribute() {
            this.AddElementName = "add";
            this.RemoveElementName = "remove";
            this.ClearElementName = "clear";
        }

        public string AddElementName { get; set; }
        public string RemoveElementName { get; set; }
        public string ClearElementName { get; set; }
    }

    public class GenericElementCollection<TElement> : ConfigurationElementCollection, IKeyedElementCollection<TElement> where TElement : ConfigurationElement, IKeyedElement, new() {
        public GenericElementCollection() {
            CollectableElementAttribute attr = (CollectableElementAttribute)Attribute.GetCustomAttribute(typeof(TElement), typeof(CollectableElementAttribute), true);
            if (attr != null) {
                this.AddElementName = attr.AddElementName;
                this.ClearElementName = attr.ClearElementName;
                this.RemoveElementName = attr.RemoveElementName;
            }
        }

        protected override ConfigurationElement CreateNewElement() {
            return new TElement();
        }

        public new TElement this[string name] {
            get {
                return (TElement)this.BaseGet(name);
            }
        }

        public TElement this[int index] {
            get {
                return (TElement)this.BaseGet(index);
            }
        }

        public void Add(TElement element) {
            this.BaseAdd(element);
        }

        public void Remove(string key) {
            this.BaseRemove(key);
        }

        public TElement CreateElement() {
            return new TElement();
        }
        protected override object GetElementKey(ConfigurationElement element) {
            return ((TElement)element).Key;
        }

        #region IEnumerable<TElement> Members

        IEnumerator<TElement> IEnumerable<TElement>.GetEnumerator() {
            System.Collections.IEnumerator enumerator = this.GetEnumerator();
            while (enumerator.MoveNext()) {
                yield return (TElement)enumerator.Current;
            }
        }

        #endregion

        #region IKeyedElementCollection Members

        ConfigurationElement IKeyedElementCollection.this[string name] {
            get {
                return this[name];
            }
        }

        void IKeyedElementCollection.Add(ConfigurationElement element) {
            this.Add((TElement)element);
        }

        void IKeyedElementCollection.Remove(ConfigurationElement element) {
            this.Remove(((TElement)element).Key);
        }

        ConfigurationElement IKeyedElementCollection.CreateElement() {
            return CreateElement();
        }

        #endregion
    }
}
